//package com.csii.common.support;
//
//import com.alibaba.druid.pool.DruidDataSource;
//import com.csii.adhoc.dataunits.dao.DataSourceDao;
//import com.csii.adhoc.dataunits.service.DataUnitsService;
//import com.csii.adhoc.dblink.DbLinkPo;
//import com.zaxxer.hikari.util.DriverDataSource;
//import org.aspectj.lang.JoinPoint;
//import org.aspectj.lang.annotation.After;
//import org.aspectj.lang.annotation.Aspect;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.BeansException;
//import org.springframework.beans.factory.BeanFactory;
//import org.springframework.beans.factory.BeanFactoryAware;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.config.BeanPostProcessor;
//import org.springframework.context.annotation.Primary;
//import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
//import org.springframework.stereotype.Component;
//
//
//import javax.sql.DataSource;
//import java.util.List;
//import java.util.Map;
//import java.util.Properties;
//import java.util.concurrent.ConcurrentHashMap;
//
///**
// * @author donglimao
// * @description 将所有的配置于数据源管理表 MGN_DB 中的所有数据源注入到 spring 容器，使用 DataSourceManager.getBean(conn_id)
// * 来获取 MGN_DG 中主键为 conn_id 的数据源
// */
//@Aspect
//@Component
//@Primary
//public class DataSourceManager extends AbstractRoutingDataSource implements BeanPostProcessor, BeanFactoryAware {
//
//    {
//        //1
//        super.setTargetDataSources(dataSourceMap);
//    }
//
//    public static final String DEFAULT_DATASOURCE_NAME = "defaultDataSource";
//a
//    private static ConcurrentHashMap<Object, Object> dataSourceMap = new ConcurrentHashMap<Object, Object>();
//
//    private static final ThreadLocal<String> CONTEXT_HOLDER = new InheritableThreadLocal<>().withInitial(() -> DEFAULT_DATASOURCE_NAME);
//
//    private static boolean beProcessed = false;
//
//    private static final Logger log = LoggerFactory.getLogger(DataSourceManager.class);
//
//    @Autowired
//    private DefaultDataSourceVO defaultDataSource;
//
//    @Autowired
//    private static BeanFactory beanFactory;
//
//    @Autowired
//    private DataSourceDao dataSourceDao;
//    private static DataSourceDao dataSourceDaoStatic;
//
//    // 内存动态切换数据源
//    public void setCurrentDataSource(String connId) {
//        CONTEXT_HOLDER.set(connId);
//    }
//
//    @Override
//    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//        //保证只执行一次
//        if (!beProcessed) {
//            Map map = loadAllDataSource();
//            dataSourceMap.putAll(map == null ? dataSourceMap : map);
//            beProcessed = true;
//        }
//        return null;
//    }
//
//    //3.
//    @Override
//    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
//        this.beanFactory = beanFactory;
//        DefaultDataSourceVO bean = beanFactory.getBean(DefaultDataSourceVO.class);
//        DruidDataSource defaultDataSource = new DruidDataSource();
//        defaultDataSource.setDriverClassName(bean.getDriverClassName());
//        defaultDataSource.setUrl(bean.getUrl());
//        defaultDataSource.setUsername(bean.getUsername());
//        defaultDataSource.setPassword(bean.getPassword());
//        dataSourceMap.put(DEFAULT_DATASOURCE_NAME, defaultDataSource);
//        super.setTargetDataSources(dataSourceMap);
//        //帮忙把 dataUnitsServiceStatic = dataUnitsService
//        dataSourceDaoStatic = dataSourceDao;
//    }
//
//
//    // 还原为默认数据源
//    public static void reset2defaultDataSource() {
//        CONTEXT_HOLDER.remove();
//    }
//
//    // 获取当前数据源的 ConnId ，对应数据库中的一条记录
//    public static String getCurrentDataSourceConnId() {
//        return CONTEXT_HOLDER.get();
//    }
//
//    /*
//    当平台启动后，若还需要根据需要动态向数据库添加数据源，并且也要将该新增数据源纳入动态切换，则需要调用本方法重新将 t_mgn_db 中
//    所有的已经配置的数据源重新载入到内存
//     */
//    public static void reloadAllDataSource() {
//        Map map = loadAllDataSourceStatic();
//        if (map != null) {
//            //始终保留 defaultDataSource
//            Object defalutDataSource = dataSourceMap.get(DEFAULT_DATASOURCE_NAME);
//            dataSourceMap.clear();
//            dataSourceMap.put(DEFAULT_DATASOURCE_NAME, defalutDataSource);
//            dataSourceMap.putAll(map);
//        }
//    }
//
//    //5
//    @Override
//    protected Object determineCurrentLookupKey() {
//        return CONTEXT_HOLDER.get();
//    }
//
//    @Override
//    protected DataSource determineTargetDataSource() {
//        Object lookupKey = determineCurrentLookupKey();
//        DataSource dataSource = (DataSource) dataSourceMap.get(lookupKey);
//        if (dataSource == null && lookupKey == null) {
//            dataSource = (DataSource) dataSourceMap.get("defaultDataSource");
//        }
//        if (dataSource == null) {
//            throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
//        }
//        return dataSource;
//    }
//
//    /*
//     从数据库重新载入所有数据库,war 包启动时会调用本方法
//    */
//    private Map loadAllDataSource() {
//        //还原为默认数据源去 t_mgn_db 中查询数据
//        List<DbLinkPo> dataSources = dataSourceDao.selectAllDataSource();
//        Map<Object, Object> dataSourcesMapTmp = new ConcurrentHashMap<>();
//        dataSources.forEach((dbLinkPo) -> {
//            DriverDataSource driverDataSource = new DriverDataSource(
//                    //构造参数1 url
//                    dbLinkPo.getUrl() == null ? "" : dbLinkPo.getUrl().trim(),
//                    //构造参数2 数据库 DriverClass
//                    dbLinkPo.getDriverClass(),
//                    //构造参数3 配置文件 properties 对象
//                    new Properties(),
//                    //构造参数4 用户名
//                    dbLinkPo.getUsername() == null ? "" : dbLinkPo.getUsername().trim(),
//                    //构造参数5 密码
//                    dbLinkPo.getPasswd() == null ? "" : dbLinkPo.getPasswd().trim()
//            );
//            dataSourcesMapTmp.put(dbLinkPo.getConnId(), driverDataSource);
//        });
//        return dataSourcesMapTmp;
//    }
//
//    /*
//     从数据库重新载入所有数据库,系统启动后，如果数据源配置表有数据有变化，可以使用
//     DataSourceManager.flushAllDataSource()来重新载入所有数据源，这时时会调用本方法a
//    */
//    public static Map loadAllDataSourceStatic() {
//        //还原为默认数据源去 t_mgn_db 中查询数据
//        reset2defaultDataSource();
//        List<DbLinkPo> dbLinkPos = dataSourceDaoStatic.selectAllDataSource();
//        Map<Object, Object> dataSourcesMapTmp = new ConcurrentHashMap<>();
//        dbLinkPos.forEach((dbLinkPo) -> {
//            DriverDataSource driverDataSource = new DriverDataSource(
//                    //构造参数1 url
//                    dbLinkPo.getUrl() == null ? "" : dbLinkPo.getUrl().trim(),
//                    //构造参数2 数据库 DriverClass
//                    dbLinkPo.getDriverClass(),
//                    //构造参数3 配置文件 properties 对象
//                    new Properties(),
//                    //构造参数4 用户名
//                    dbLinkPo.getUsername() == null ? "" : dbLinkPo.getUsername().trim(),
//                    //构造参数5 密码
//                    dbLinkPo.getPasswd() == null ? "" : dbLinkPo.getPasswd().trim()
//            );
//            dataSourcesMapTmp.put(dbLinkPo.getConnId(), driverDataSource);
//        });
//        return dataSourcesMapTmp;
//    }
//
//    /*
//     根据 connId 返回 DataSource，必须存在于数据源池中
//    */
//    public static DataSource getConnIdDataSource(String connId) {
//        return (DataSource) dataSourceMap.get(connId);
//    }
//
//    public static Object getBean(Class clazz) {
//        return beanFactory.getBean(clazz);
//    }
//
//    //切面说明：当进入到 @Service 层时，将数据源恢复为缺省数据源，如果要使用其它数据源，则可以在@Service 层再转换为其它数据源
//    @After("(execution(* com.csii..DataUnitsDao.*(..)))")
//    public void after(JoinPoint joinPoint) {
//        DataSourceManager.reset2defaultDataSource();
//    }
//}